package shell;

import java.util.HashSet;
import java.util.Set;

import games.Coordinate;
import games.KamisadoGUI;
import games.KamisadoSquare;
import games.KamisadoState;
import games.KamisadoStateH1;
import games.KamisadoStateH2;
import games.ErikHeuristic;
import games.SquareColor;
import games.Tower;
import games.Controller;
import games.KamisadoState.KamisadoMove;
import games.MikaelHeuristic;

/**
 *
 * @author Erik
 */
public class KamisadoGame extends AbstractGame<KamisadoMove, KamisadoState> {

    private static KamisadoGUI gui = null;
    private static Controller controller;
    private static Set<String> STATES;

    static {
        STATES = new HashSet<String>();
        STATES.add("computer");
        STATES.add("h1");
        STATES.add("h2");
        STATES.add("erik");
        STATES.add("mikael");
    }

    public KamisadoGame(String[] args) {
        super(KamisadoState.class, 9, args);
    }

    public static void main(String[] args) {
        System.out.println("\n\nComputer playing from bottom");
        System.out.println("Move syntax: color,x,y");
        System.out.println("Ex: green,6,5 is valid in first round\n\n");
        controller = new Controller();
        new KamisadoGame(args).play();
    }

    @Override
    protected Set<String> availableStates() {
        return STATES;
    }

    @Override
    protected KamisadoState createState(String name) {
        if ("h1".equals(name)) {
            return new KamisadoStateH1();
        } else if ("h2".equals(name)) {
            return new KamisadoStateH2();
        } else if ("erik".equals(name)) {
            return new ErikHeuristic();
        } else if ("mikael".equals(name)) {
            return new MikaelHeuristic();
        } else {
            return new KamisadoState();
        }
    }

    @Override
    protected String render(KamisadoState game) {
        KamisadoMove move = game.getPreviousMove();
        return move != null ? move.toString() : "No moves";
        /*StringBuilder buffer = new StringBuilder();
        for (int y = 7; y >= 0; y--) {
        buffer.append(y + "|");
        for (int x = 0; x < 8; x++) {
        KamisadoSquare ks = game.cell(x, y);
        String s = "";
        if (ks.getTower() == null) {
        s = ks.getColor() + "/" + ks.getTower();
        } else {
        s = ks.getColor() + "/" + ks.getTower().getColor();
        }
        buffer.append(s);
        if (x < 8) {
        buffer.append("\t|");
        }
        }
        buffer.append("\n");
        }
        buffer.append(" |0\t\t| 1\t\t| 2\t\t| 3\t\t| 4\t\t| 5\t\t| 6\t\t| 7\n");
        return buffer.toString();*/
    }

    @Override
    protected void displayGUI(KamisadoState game) {
        if (gui == null) {
            gui = new KamisadoGUI(controller);
        }

        gui.createAndShowGUI(game);
    }

    @Override
    protected KamisadoMove parseMove(KamisadoState state, String command) {
        KamisadoMove result;
        try {
            String[] coordinates = command.split(",");
            String strTower = coordinates[0].toUpperCase();
            int x = Integer.parseInt(coordinates[1]);
            int y = Integer.parseInt(coordinates[2]);

            Tower tower = new Tower(SquareColor.valueOf(strTower), false);

            // Find old values for x and y.
            Coordinate c = state.getCurrentPosition(tower);

            result = new KamisadoMove(x, y, c.getX(), c.getY(), tower);
            if (state.isValidMove(result)) {
                return result;
            }

        } catch (NumberFormatException e) {
            result = null;
        }
        return null;
    }

    @Override
    protected KamisadoMove waitForMove(KamisadoState state) {
        System.out.println("Waiting for move");
        while (!controller.userMadeAMove()) {
            sleep(500);
        }
        Coordinate moveTo = controller.getCoordinate();
        Coordinate moveFrom;
        Tower tower;
        KamisadoMove m = state.getPreviousMove();
        boolean player = state.player();
        System.out.println(player);
        if (m == null) { // First move
            moveFrom = controller.getOldCoordinate();
            KamisadoSquare ks = state.cell(moveFrom.X, moveFrom.Y);
            tower = new Tower(ks.getColor(), player);
        } else {
            KamisadoSquare ks = state.cell(m.getX(), m.getY());
            tower = new Tower(ks.getColor(), player);
            moveFrom = state.getCurrentPosition(tower);
        }

        KamisadoMove result = new KamisadoMove(moveTo.getX(), moveTo.getY(), moveFrom.getX(), moveFrom.getY(), tower);
        if (state.isValidMove(result)) {
            return result;
        }

        return null;
    }

    private void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
